#include "component.h"
#include "device.h"
#include "motor_dai.h"

#include "export.h"
#include "debug_config.h"

// 将其他配置放置xxx_iocfg.h中
//HALL1-->B22、HALL2-->B24、HALL3-->B23、OCEP1-->B20、OCEP1-->B21
#ifndef HALL1_SET_LEVEL
#define HALL1_SET_LEVEL (1)
#endif
#define HALL1_RESET_LEVEL (!HALL1_SET_LEVEL)

#ifndef HALL2_SET_LEVEL
#define HALL2_SET_LEVEL (0)
#endif
#define HALL2_RESET_LEVEL (!HALL2_SET_LEVEL)

#ifndef HALL3_SET_LEVEL
#define HALL3_SET_LEVEL (0)
#endif
#define HALL3_RESET_LEVEL (!HALL3_SET_LEVEL)

#ifndef OCEP1_SET_LEVEL
#define OCEP1_SET_LEVEL (0)
#endif
#define OCEP1_RESET_LEVEL (!OCEP1_SET_LEVEL)

#ifndef OCEP2_SET_LEVEL
#define OCEP2_SET_LEVEL (0)
#endif
#define OCEP2_RESET_LEVEL (!OCEP2_SET_LEVEL)

#ifndef MOTOR_POWER_ENABLE_LEVEL
#define MOTOR_POWER_ENABLE_LEVEL (1)
#endif
#define MOTOR_POWER_DISABLE_LEVEL (!MOTOR_POWER_ENABLE_LEVEL)

#ifndef IR_POWER_ENABLE_LEVEL
#define IR_POWER_ENABLE_LEVEL (1)
#endif
#define IR_POWER_DISABLE_LEVEL (!IR_POWER_ENABLE_LEVEL)

#ifndef LOCK_SYSTEM_ID
#define LOCK_SYSTEM_ID COMP_LOCK
#endif
/* 电机供电电压控制脚（电压高时降压）*/
#ifndef MOTOR_POWER_CTRL_VAL 
#define MOTOR_POWER_CTRL_VAL 5500
#endif
/* 电机供电电压控制脚 高电压时输出电平*/
#ifndef MOTOR_HIGH_VOLTAGE_LEVEL 
#define MOTOR_HIGH_VOLTAGE_LEVEL 0
#endif
/* 电机供电电压控制脚 高电压时输出电平*/
#ifndef MOTOR_SLEEP_VOLTAGE_LEVEL 
#define MOTOR_SLEEP_VOLTAGE_LEVEL 0
#endif

/* 电机电流采集的ADC通道 */
#define LOCK_DCI_ADC_CHANNEL                    vADC_1
#define MOTO_A_VIRTUAL_PWM                      vPWM_1
#define MOTO_B_VIRTUAL_PWM                      vPWM_2
#define SENSOR_HALL_LEFT                        vPIN_B22
#define SENSOR_HALL_RIGHT                       vPIN_B23
#define SENSOR_HALL_CENTER                      vPIN_B24


#define LOCK_IR_ENABLE()                        Device_Write(vPIN_C0, NULL, 0, IR_POWER_ENABLE_LEVEL) //开启红外光耦电源
#define LOCK_IR_DISABLE()                       Device_Write(vPIN_C0, NULL, 0, IR_POWER_DISABLE_LEVEL) //关闭红外光耦电源

#define LOCK_MOTOR_ENABLE()                     Device_Write(vPIN_C2, NULL, 0, MOTOR_POWER_ENABLE_LEVEL) //开启电机驱动电源
#define LOCK_MOTOR_DISABLE()                    Device_Write(vPIN_C2, NULL, 0, MOTOR_POWER_DISABLE_LEVEL) //关闭电机驱动电源

#define LOCK_MOTOR_POWER_HIGH_VOLTAGE()         Device_Write(vPIN_C45, NULL, 0, MOTOR_HIGH_VOLTAGE_LEVEL); // 电机输入电压高
#define LOCK_MOTOR_POWER_LOW_VOLTAGE()          Device_Write(vPIN_C45, NULL, 0, !MOTOR_HIGH_VOLTAGE_LEVEL); // 电机输入电压低
#define LOCK_MOTOR_POWER_SLEEP_VOLTAGE()        Device_Write(vPIN_C45, NULL, 0, MOTOR_SLEEP_VOLTAGE_LEVEL); // 休眠IO配置

/* 事件 */
#define EVENT_MOTOR_MONITOR                     (0X00000001)  //电机监控事件
#define EVENT_AUTO_LOCK                         (0X00000002)  //自动上锁事件
#define EVENT_LOCK_DIR_UPDATE                   (0X00000004)  //上电同步上锁方向

#define NO_BRAKE                                  
/* 电机控制参数 */
#define MOTOR_PARAM_MAX_REPEAT_TIMES            3       //最大重复次数（上锁/开锁失败后，会自动重复3次）
#define MOTOR_PARAM_MAX_DCI_VALUE               200     //电压为200mv 采样电阻0.5Ω 换算成电机堵转限制电流400mA 
#define MOTOR_PARAM_LOCKED_MORE_TIME            50      //上锁过推时间
#define MOTOR_PARAM_BLOCK_STOP_TIMEOUT          1000    //堵转停止超时时间
#define MOTOR_PARAM_STOP_TIME1                  200     //电机暂停时间1（开锁堵转暂停时间、开关锁超时）
#define MOTOR_PARAM_TURN_TIMEOUT                4000    //电机正常运行，超时时间
#define MOTOR_PARAM_BACK_TIMEOUT                2000    //电机回拖运行，超时时间
#define MOTOR_PARAM_DCI_DETECT_DELAY_TIME       80      //电机启动后，电流检测延迟时间
#define MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME    1000     //换方向时间 切换方向时间必须>1s(包含刹车时间)
#define MOTOR_PARAM_BRAKE_TIME                  500     //电机刹车时间  刹车时间需要确认是否充足
#define MOTOR_PARAM_CHANGE_DIR_TIME             500     //换方向时间 切换方向时间必须>1s(包含刹车时间)
#define MOTOR_PARAM_STOP_TO_BRAKE_TIME          10      //10ms 
// #define STOP_TO_BRAKE


/* 电机监测时间间隔 */
#define MOTOR_MONITOR_TIME                      (10)    //电机监测时间间隔 10ms
#define AUTO_LOCK_EVENT_TIME                    (1)     //自动上锁事件
/* 电机上锁堵转重新操作锁体的时间间隔 */
#define MOTOR_BLOCKED_LOCKED_TIME               (1000)
/* 电机开锁堵转重新操作锁体的时间间隔 */
#define MOTOR_BLOCKED_UNLOCK_TIME               (100)  

#define MOTOR_BLOCKED_FILETERED_TIME            (50)    //堵转过滤时间 50ms
#define MOTOR_BLOCKED_FILETERED_TIMES           (MOTOR_BLOCKED_FILETERED_TIME/MOTOR_MONITOR_TIME)

#define SENSOR_MAX_RING_LEN                     (10) // 整个锁体流程最多8个数据变化 + 光耦上电时最多2个

/****NV item ID****/
typedef enum
{
    NVAUTO_CALFLAG,
    NVMOTO_DIR,
} LockNvItemID_enum_t;
/****NV item ID****/

/****NV sub ID****/
//不需要sub ID
/****NV sub ID****/

/* 锁体状态 */
static enum {
    LOCK_STA_UNKNOW,     //未知状态
    LOCK_STA_LOCKING,    //正在上锁
    LOCK_STA_UNLOCKING,  //正在开锁
    LOCK_STA_LOCKED,     //已上锁
    LOCK_STA_UNLOCK,     //已开锁
} lockStatus = LOCK_STA_UNKNOW;


/* 传感器状态类型 */
typedef enum
{
	LOCK_SENSOR_UNKNOW,  //传感器状态未知
	LOCK_SENSOR_SET,     //传感器状态：到位（感应到了）
	LOCK_SENSOR_LONG_SET,//传感器状态：长时间到位（长按）
	LOCK_SENSOR_RESET,   //传感器状态：未到位（没感应到）
}SensorStatus_enum_t;

/* 自动上锁/开锁步骤*/
typedef enum
{
	LOCK_STEP_START,           //启动
	LOCK_STEP_FOUND_DEST,      //上锁/开锁到位
	LOCK_STEP_BACKED,          //上锁/开锁回拖到位
	LOCK_STEP_RESET,           //传感器状态：未到位（没感应到）
}LockStep_enum_t;

static TimerHandle_stu_t Auto_Lock_Timer = NULL;

/* 电机状态数据 */
static struct
{
	volatile MotorStatus_enum_t current; //电机当前状态 
	volatile uint32_t startTime;         //电机当前状态开始时间
	volatile uint32_t timeout;           //电机当前状态超时时间
}motorStatus = {MOTOR_STA_IDLE, MOTOR_STA_IDLE};


/* 电机运行错误情况 */
volatile static enum
{
	ERR_NO_ERROR,       //无错误
	ERR_LOCK_ERROR,     //锁体错误（电机运转结束时，传感器状态不对）
 
	ERR_LOCKED_TIMEOUT, //上锁超时
	ERR_UNLOCK_TIMEOUT, //开锁超时
	ERR_BACK_TIMEOUT,   //回拖超时
    ERR_RESET_TIMEOUT,  //回位超时
 
	ERR_LOCKED_DCI,     //上锁过流
	ERR_UNLOCK_DCI,     //开锁过流
	ERR_BACK_DCI,       //回拖过流
    ERR_RESET_DCI,      //回位过流
}motorError = ERR_NO_ERROR;

/* 电机刹车原因类型 */
typedef enum
{
	MOTOR_BRAKE_NO_SOURCE,              //无刹车源
    MOTOR_BRAKE_LOCKED,                 //上锁刹车
    MOTOR_BRAKE_UNLOCK,                 //开锁刹车
    MOTOR_BRAKE_RESET,                  //回位刹车
}MotorBrakeSource_enum_t;

/* 上锁方向类型 */
typedef enum
{
	LOCKED_DIR_UNKNOWN,                 //未知上锁方向
    LOCKED_DIR_CW,                      //顺时针上锁方向
    LOCKED_DIR_CCW,                     //逆时针上锁方向
}Locked_Dir_enum_t;//旋钮

/* 上锁堵住阶段控制类型 */
typedef enum
{
	LOCKED_BLOCK_INIT,                  //初始状态
    LOCKED_BLOCK_LOCKED,                //上锁堵转,当前阶段为上锁阶段
    LOCKED_BLOCK_UNLOCK,                //上锁堵转,当前阶段为开锁阶段
}Locked_Block_Phase_enum_t;


/* 传感器测试阶段类型 */
typedef enum
{
	SENSOR_TESTSETP_INIT,               //初始状态
    SENSOR_TESTSETP_START,              //启动阶段
    SENSOR_TESTSETP_END,                //结束阶段
    SENSOR_TESTSETP_RESET,              //回位阶段
    SENSOR_TESTSETP_RESET_BACK,         //回位回拖阶段
}Lock_Sensor_TestSetp_enum_t;

static RingBufferHandle_t rbHandle = NULL;
static  FlagStatus g_unlockChgFlag = SET;//开锁传感器变化标志;  SET:变化   RESET:没变化
static  FlagStatus g_lockChgFlag = SET;  //关锁传感器变化标志;  SET:变化   RESET:没变化
/* 锁体模式 */
__EFRAM static Locked_Mode_enum_t lockedMode = LOCKED_MODE_NORMAL;

/* 锁校准标志 */
__EFRAM static FlagStatus lockCalibFlag = RESET;

/* 上锁方向 */
__EFRAM static Locked_Dir_enum_t lockedDir = LOCKED_DIR_UNKNOWN;

/* 上锁堵转标志 */
static FlagStatus lockedBlock = RESET;

/* 上锁执行回拖标志 */
static FlagStatus lockedBack = RESET;

/* 开锁执行回拖标志 */
static FlagStatus unLockBack = RESET;

/* 上锁堵转后的锁体控制阶段 */
static Locked_Block_Phase_enum_t lockedBlockPhase = LOCKED_BLOCK_INIT;

/* 传感器测试阶段 */
static Lock_Sensor_TestSetp_enum_t sensorTestSetp = SENSOR_TESTSETP_INIT;

/* 传感器测试结果 */
static uint16_t sensorTestRet = 0;

volatile static uint8_t repeatCount;        //重复上锁计数
volatile static uint8_t isrPendFlag;        //中断挂起标志
volatile SensorStatus_enum_t leftLockedSensor = LOCK_SENSOR_UNKNOW;     //左侧(面向磁铁)上锁传感器
volatile SensorStatus_enum_t rightLockedSensor = LOCK_SENSOR_UNKNOW;    //右侧(面向磁铁)上锁传感器
__EFRAM volatile SensorStatus_enum_t lockedSensor = LOCK_SENSOR_UNKNOW;         //上锁传感器(左右上锁传感器两个都没上锁则没上锁,否则即是已上锁)
__EFRAM volatile SensorStatus_enum_t unlockSensor = LOCK_SENSOR_UNKNOW;         //开锁传感器
__EFRAM volatile SensorStatus_enum_t backLockedSensor = LOCK_SENSOR_UNKNOW;     //开锁到位、上锁回拖到位传感器
__EFRAM volatile SensorStatus_enum_t backUnlockSensor = LOCK_SENSOR_UNKNOW;     //上锁到位、开锁回拖到位传感器
volatile static uint8_t g_IrPowerSwitch = RESET;//光耦电源开关标志，默认关
static uint8_t g_BrakeFlag = DISABLE;//ENABLE:刹车动作标志   

LockNvData_stu_t lock_data = { 0, MOTO_DIR_CW };


static MOTO_STATUS_E       moto_status                 = MOTO_STOP_LOCK_UNKNOWN;    //锁体当前状态（转动、关锁、开锁）
static LockStep_enum_t     g_current_step              = LOCK_STEP_START;                //锁体当前步骤（启动、到位、回拖、回位）
/**
 * @brief  获取锁状态
 * @note
 *
 *
 */
static uint8_t Lock_get_lock_status(void)
{
    if(motorStatus.current != MOTOR_STA_IDLE)
    {
        moto_status = MOTO_ROTATE;
    }
    else
    {
        if(lockStatus == LOCK_STA_LOCKING || lockStatus == LOCK_STA_LOCKED)
        {
            moto_status = MOTO_STOP_LOCK_CLOSE;
        }
        else if(lockStatus == LOCK_STA_UNLOCKING || lockStatus == LOCK_STA_UNLOCK)
        {
            moto_status = MOTO_STOP_LOCK_OPEN;
        }
        else
        {
            moto_status = MOTO_STOP_LOCK_UNKNOWN;
        }
    }
    return moto_status;
}

/**
 * @brief 设置光耦电源开关
 * 
 * @param ir_power_level :开关电平
 */
static void Lock_OptocoupleCtrl(uint8_t ir_power_level)
{
    if(ir_power_level == IR_POWER_DISABLE_LEVEL)//关光耦电源
    {       
        LOCK_IR_DISABLE();    
        g_IrPowerSwitch = RESET;   
    }
    else//开光耦电源
    {
        LOCK_IR_ENABLE(); 
        g_IrPowerSwitch = SET;  
    }
    LOCKDAI_LOG_V("ir switch:%d",g_IrPowerSwitch);
}

/**
 * @brief 获取自适应方向的标志位
 * 
 * @return 产测写入的自适应方向标志位 
 */
static uint8_t lock_CalflagGet(void)
{
    if (OSAL_NvRead(OSAL_OFFSET(LockNvData_stu_t, g_autoCalFlag), (void *)&lock_data.g_autoCalFlag,
                    sizeof(lock_data.g_autoCalFlag)) != SUCCESS)  // TODO 读取NV存储的电机方向
    {
        /*读取失败处理*/
    }
    if (lock_data.g_autoCalFlag != SET)
    {
        lock_data.g_autoCalFlag = RESET;
    }
    return lock_data.g_autoCalFlag;
}

/**
 * @brief 设置自适应方向的标志位
 * 
 * @param flag：1：设置自适应方向标志 0：清除自适应方向标志
 */
static void lock_CalflagSet(uint8_t flag)
{
    lock_data.g_autoCalFlag = flag;
    if (OSAL_NvWrite(OSAL_OFFSET(LockNvData_stu_t, g_autoCalFlag), (void *)&lock_data.g_autoCalFlag,
                     sizeof(lock_data.g_autoCalFlag)) != SUCCESS)
    {
        /*写入失败处理*/
    } 
}

/**
 * @brief 打开电机和光耦的锁体控制的配置
 * 
 */
static void Lock_CtrlOpen(void)
{
    Motor_Stop();
    /* 打开PWM和ADC */
    Device_Enable(MOTO_A_VIRTUAL_PWM);
    Device_Enable(MOTO_B_VIRTUAL_PWM);
    Device_Enable(LOCK_DCI_ADC_CHANNEL);
    /* 光耦电机通电 */
    LOCK_MOTOR_ENABLE();
    LOCK_IR_ENABLE();    
    g_IrPowerSwitch = SET;
    LOCKDAI_LOG_V("ir switch:%d",g_IrPowerSwitch);
}


/**
 * @brief 关闭电机和光耦的锁体控制配置
 * 
 */
static void Lock_CtrlClose(void)
{
    //1.pwm关掉  2.配置普通GPIO，低电平停止电机
    Motor_Stop();
    /* 关闭PWM和ADC */
    Device_Disable(MOTO_A_VIRTUAL_PWM);
    Device_Disable(MOTO_B_VIRTUAL_PWM);
    Device_Disable(LOCK_DCI_ADC_CHANNEL);
    /* 光耦电机断电 */
    LOCK_MOTOR_DISABLE();
    LOCK_IR_DISABLE(); 
    g_IrPowerSwitch = RESET;
    LOCKDAI_LOG_V("ir switch:%d",g_IrPowerSwitch);
}

/**
  * @brief  上报电机方向
  * @note   
  *
  * @param  flag：0: 左方向上锁（逆时针） 1:右方向上锁（顺时针）
  */
static void Lock_MotorDirReport(uint8_t flag)
{
    LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
    if(flag)
    {
        lockMsg.lock = LOCK_ACTION_DIR_RIGHT;
    }
    else
    {
        lockMsg.lock = LOCK_ACTION_DIR_LEFT;
    }
    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
}

/**
  * @brief  切换电机状态
  * @note   
  *
  * @param  status：需要切换的状态
  * @param  timeout：该状态的超时时间
  */
static void Lock_SwitchMotorStatus(MotorStatus_enum_t status, uint32_t timeout)
{
    isrPendFlag++;
    #ifdef STOP_TO_BRAKE
    MotorStatus_enum_t temp = status;//保存一份
    static MotorStatus_enum_t last_status = MOTOR_STA_IDLE;
    
    if ((MOTOR_STA_LOCKED_BRAKE == temp ||
            MOTOR_STA_UNLOCK_BRAKE == temp || 
			MOTOR_STA_LOCKED_BACK_BRAKE == temp ||
            MOTOR_STA_UNLOCK_BACK_BRAKE == temp ||
            MOTOR_STA_LOCKED_RESET_BRAKE == temp || 
            MOTOR_STA_UNLOCK_RESET_BRAKE == temp ))
    {
        status = MOTOR_STA_STOP;    
        last_status =  temp; 
    }
    else if((MOTOR_STA_STOP == temp) && (MOTOR_STA_LOCKED_BRAKE == last_status ||
            MOTOR_STA_UNLOCK_BRAKE == last_status || 
			MOTOR_STA_LOCKED_BACK_BRAKE == last_status ||
            MOTOR_STA_UNLOCK_BACK_BRAKE == last_status ||
            MOTOR_STA_LOCKED_RESET_BRAKE == last_status || 
            MOTOR_STA_UNLOCK_RESET_BRAKE == last_status ))
    {
        status = last_status;   
        last_status =  temp;  
        g_BrakeFlag =  ENABLE;
    }
    else
    {

        last_status =  MOTOR_STA_IDLE;  
    }
    #endif      
	motorStatus.current = status;
	motorStatus.timeout = timeout;
	motorStatus.startTime = OSAL_GetTickCount();

    LOCKDAI_LOG_D("motor action:%d",motorStatus.current);

    if (MOTOR_STA_LOCKED_BACK == motorStatus.current)
	{
        /* 上锁回拖 */
        Motor_TurnLeft();//上锁回拖操作跟开锁操作控制电机的方向是一致的
	}
    else if (MOTOR_STA_UNLOCK_BACK == motorStatus.current)
	{
        /* 开锁回拖 */
        Motor_TurnRight();//开锁回拖操作跟上锁操作控制电机的方向是一致的
    }
    else if (MOTOR_STA_LOCKED_RESET == motorStatus.current)
	{
        /* 上锁回位 */
        Motor_TurnLeft();//上锁回位操作跟开锁操作控制电机的方向是一致的
	}
    else if (MOTOR_STA_UNLOCK_RESET == motorStatus.current)
	{
        /* 开锁回位 */
        Motor_TurnRight();//开锁回位操作跟上锁操作控制电机的方向是一致的
    }
	else if (MOTOR_STA_LOCKED_BRAKE == motorStatus.current ||
            MOTOR_STA_UNLOCK_BRAKE == motorStatus.current || 
			MOTOR_STA_LOCKED_BACK_BRAKE == motorStatus.current ||
            MOTOR_STA_UNLOCK_BACK_BRAKE == motorStatus.current ||
            MOTOR_STA_LOCKED_RESET_BRAKE == motorStatus.current || 
            MOTOR_STA_UNLOCK_RESET_BRAKE == motorStatus.current )
	{
		/* 刹车 */
		Motor_Brake();
	}
	else if (MOTOR_STA_LOCKED == motorStatus.current)
	{
		/* 电机上锁 */
		Motor_TurnRight();
	}
	else if (MOTOR_STA_UNLOCK == motorStatus.current)
	{
		/* 电机开锁 */
		Motor_TurnLeft();
	}
	else
	{
		/* 电机停止 */
		Motor_Stop();
	}
    #ifdef STOP_TO_BRAKE
    motorStatus.current = temp;
    #endif       
    isrPendFlag--;
}

/**
  * @brief  处理上锁流程结束
  *         
  * @note   
  */
static void Lock_MotorLockedEnd(void)
{
    uint8_t repeatTotal; 
    LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
    LOCKDAI_LOG_D("lock hall&oc sta:%d,%d", lockedSensor,backLockedSensor);
    //如果锁还没有完成校准,那么堵转后,需要同方向重试2次，再反方向重试3次,直到上锁成功才完成校准
    //如果锁已经完成了校准,那么堵转后只需要同方向再重试2次就可以了
    repeatTotal = (lockCalibFlag == RESET) ? (MOTOR_PARAM_MAX_REPEAT_TIMES * 2 - 1) : (MOTOR_PARAM_MAX_REPEAT_TIMES - 1);
    /* 发生堵塞了 */
    if(lockedBlock)
    {
        LOCKDAI_LOG_V("LockBlock:%d,%d,%d",lockedBlockPhase, repeatCount, repeatTotal);
		if(lockedBlockPhase == LOCKED_BLOCK_INIT || lockedBlockPhase == LOCKED_BLOCK_LOCKED)
        {
            lockedBlockPhase = LOCKED_BLOCK_UNLOCK;
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK, MOTOR_PARAM_TURN_TIMEOUT);//开锁方向
            return;
        }
        if(repeatCount < repeatTotal)   //重新上锁次数没有超过规定次数，则重新上锁
        {
            // 0 1 换向(2 3 5） 
            repeatCount++;
            //上电未校准锁方向时需要校准，前两次不需换向,后三次才需要换向
            if( (lockCalibFlag == RESET) && (repeatCount == MOTOR_PARAM_MAX_REPEAT_TIMES - 1))
            {
                Motor_ChangeDirection();
            }
            motorError = ERR_NO_ERROR;
            lockedBlockPhase = LOCKED_BLOCK_LOCKED;//标记为上锁阶段
            Lock_SwitchMotorStatus(MOTOR_STA_LOCKED, MOTOR_PARAM_TURN_TIMEOUT);
        }
        else if(repeatCount == repeatTotal)//3次(或6次,视锁方向校准情况而定)上锁失败，则执行上锁回位操作(此时处于开锁状态了,只需执行开锁回拖即可) 
        {
            LOCKDAI_LOG_I("lock reset");
            repeatCount++;
            lockedBack = SET;
            lockMsg.lock = LOCK_ACTION_DCI_ERROR;//锁体过流
            OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BACK, MOTOR_PARAM_TURN_TIMEOUT);
        }
        else
        {
            LOCKDAI_LOG_W("locked failed");
            motorError = ERR_LOCK_ERROR;
            repeatCount = 0;
            OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);

            lockMsg.lock = LOCK_ACTION_INVALID;//消息上报
            OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));

            motorError = ERR_NO_ERROR;
            motorStatus.current = MOTOR_STA_IDLE;
        }
        lockedBlock = RESET;
    }
    else // 没有发生堵塞
    {
        //上锁到位传感器(右光耦)未到位,有3种情况:
        //1.上锁超时,
        //2.上锁完成但未完成回拖时,右光耦到位后刹车时,旋钮逆时针回旋了一点,导致刹车停止后程序执行到此处时程序判断到右光耦未到位,此时需要回拖
        //3.上锁到位并回拖完成
        if(backUnlockSensor == LOCK_SENSOR_RESET)//IR_LOCK没感应到
        {
            if ( motorError == ERR_LOCKED_TIMEOUT  ) //1.上锁超时
            {
                LockMsg_t lockMsg;
                memset(&lockMsg, 0, sizeof(lockMsg));
                LOCKDAI_LOG_W("locked timeout");
                motorError = ERR_LOCK_ERROR;
                OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);

                lockMsg.lock = LOCK_ACTION_ABNORMAL;//消息上报
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));

                motorError = ERR_NO_ERROR;
                motorStatus.current = MOTOR_STA_IDLE;   
            }
            else
            {
                motorError = ERR_NO_ERROR;
                if(lockedBack == RESET)//2.情况2,需要执行回拖
                {
                    lockedBack = SET;
                    // lockMsg.lock = LOCK_ACTION_LOCKED_NO_BACK;//消息上报
                    // OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                    Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BACK, MOTOR_PARAM_BACK_TIMEOUT);
                    return;
                }
                if (lockCalibFlag == RESET && lockedMode != LOCKED_MODE_TEST && (repeatCount != repeatTotal + 1))  // 校准方向不依赖开关锁流程是否成功//双向学习不成功回拖至开锁回拖位置实际失败
                {
                    LOCKDAI_LOG_I("calibrate finished");
                    Motor_SaveDirection();

                    lockCalibFlag = SET;  // 上锁成功即是标记锁已完成校准
                    motorError    = ERR_NO_ERROR;
                    /* 上报上锁方向 */
                    Lock_MotorDirReport(Motor_GetDirection());

                    /* 更新上锁方向 */
                    if (Motor_GetDirection() == MOTO_DIR_CCW)  // 上锁方向为逆时针
                    {
                        lockedDir = LOCKED_DIR_CW;
                    }
                    else
                        lockedDir = LOCKED_DIR_CCW;
                }
                //3.上锁到位并回拖完成
                lockedBack = RESET;
                OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);
                if(lockedSensor == LOCK_SENSOR_RESET)//此时还没有把门锁上,说明开锁失败
                {
                    LOCKDAI_LOG_W("locked failed");
                    lockMsg.lock = LOCK_ACTION_INVALID;//消息上报
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
                else//门锁上了,说明上锁成功
                {
                    LOCKDAI_LOG_I("locked succeed");
                    lockMsg.lock = LOCK_ACTION_LOCKED;//消息上报
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
                motorError = ERR_NO_ERROR;
                motorStatus.current = MOTOR_STA_IDLE;//标记锁的状态为空闲
            }
        }
        //上锁传感器(右光耦)到位了，此处情况有2种: 
        //1.上次执行上锁操作,导致上锁到位了,此时需要执行回拖操作 
        //2.上次执行了回位操作,此时不需要执行回拖操作了 
        else
        {
            if(repeatCount == repeatTotal + 1)//情况2,不需要执行回拖操作
            {
                LOCKDAI_LOG_W("locked failed!");
                motorError = ERR_LOCK_ERROR;
                repeatCount = 0;
                OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);

                lockMsg.lock = LOCK_ACTION_INVALID;//消息上报
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));

                motorError = ERR_NO_ERROR;
                motorStatus.current = MOTOR_STA_IDLE;
            }
            else//情况1,需要执行回拖操作
            {
                if(g_current_step == LOCK_STEP_FOUND_DEST)
                {
                    motorError = ERR_NO_ERROR;
                    lockedBack = SET;
                    Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BACK, MOTOR_PARAM_BACK_TIMEOUT);
                }
                else if(g_current_step == LOCK_STEP_BACKED)
                {
                    OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);
                    if (lockedSensor == LOCK_SENSOR_RESET)  // 此时还没有把门锁上,说明开锁失败
                    {
                        LOCKDAI_LOG_W("locked failed");
                        lockMsg.lock = LOCK_ACTION_INVALID;  // 消息上报
                        OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                    }
                    else  // 门锁上了,说明上锁成功
                    {
                        LOCKDAI_LOG_I("locked succeed");
                        lockMsg.lock = LOCK_ACTION_LOCKED;  // 消息上报
                        OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                    }
                    motorError = ERR_NO_ERROR;
                    motorStatus.current = MOTOR_STA_IDLE;  // 标记锁的状态为空闲
                }

            }
        }
    }
}

/**
  * @brief  处理开锁流程结束
  *         
  * @note   
  */
static void Lock_MotorUnlockEnd(void)
{
    uint8_t repeatTotal;
    LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
    
    //如果锁还没有完成校准,那么堵转后,需要同方向重试2次，再反方向重试3次,直到开锁成功才完成校准
    //如果锁已经完成了校准,那么堵转后只需要同方向再重试2次就可以了
    repeatTotal = (lockCalibFlag == RESET) ? (MOTOR_PARAM_MAX_REPEAT_TIMES * 2 - 1) : (MOTOR_PARAM_MAX_REPEAT_TIMES - 1);
    LOCKDAI_LOG_D("unlock hall&oc sta:%d,%d", unlockSensor,backUnlockSensor);
    //开锁传感器(下光耦)未到位,有4种情况,
    //1.开锁堵塞
    //2.开锁超时  
    //3.开锁完成但未完成回拖时,下光耦到位后刹车时,旋钮逆时针或顺时针回旋了一点,导致刹车停止后程序执行到此处时程序判断到下光耦未到位,此时需要回拖
    //4.开锁到位并完成回拖
    if(backLockedSensor == LOCK_SENSOR_RESET)//IR_UNLOCK位置
    { 
        if ( motorError == ERR_UNLOCK_DCI )   //1.开锁堵塞了
        {
            LOCKDAI_LOG_V("unlock repeat %d times",repeatCount);
            if(repeatCount < repeatTotal)   //重新开锁次数没有超过规定次数，则重新开锁
            {
                //上电未校准锁方向时需要校准，前两次不需换向,后三次才需要换向
                if( (lockCalibFlag == RESET) && (repeatCount == MOTOR_PARAM_MAX_REPEAT_TIMES - 1) )
                {
                    Motor_ChangeDirection();
                }
                repeatCount++;
                motorError = ERR_NO_ERROR;
                Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK, MOTOR_PARAM_TURN_TIMEOUT);
            }
            else if(repeatCount == repeatTotal)//3次(或6次,视锁方向校准情况而定)开锁失败，则执行开锁回位操作
            {
                LOCKDAI_LOG_I("unLock Reset");
                repeatCount++;
                unLockBack = SET;
                Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_RESET, MOTOR_PARAM_TURN_TIMEOUT);

                lockMsg.lock = LOCK_ACTION_DCI_ERROR;//锁体过流
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            }
            else
            {
                LOCKDAI_LOG_W("unlock failed");
                motorError = ERR_LOCK_ERROR;
                repeatCount = 0;
                OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);

                lockMsg.lock = LOCK_ACTION_INVALID;//消息上报
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));

                motorError = ERR_NO_ERROR;
                motorStatus.current = MOTOR_STA_IDLE;
            }
        }
        else if ( motorError == ERR_UNLOCK_TIMEOUT ) //2.开锁超时,不需要执行回拖
        {
            LOCKDAI_LOG_W("unlock failed");
            motorError = ERR_LOCK_ERROR;
            OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);

            lockMsg.lock = LOCK_ACTION_ABNORMAL;//消息上报
            OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));

            motorError = ERR_NO_ERROR;
            motorStatus.current = MOTOR_STA_IDLE;
        }
        else
        {
            motorError = ERR_NO_ERROR;
            if(unLockBack == RESET)//3.情况3,需要执行回拖操作
            {
                unLockBack = SET;
                // lockMsg.lock = LOCK_ACTION_UNLOCK_NO_BACK;//消息上报
                // OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BACK, MOTOR_PARAM_BACK_TIMEOUT);
                return;
            }
            if (lockCalibFlag == RESET && lockedMode != LOCKED_MODE_TEST && (repeatCount != repeatTotal + 1))  // 校准方向不依赖开关锁流程是否成功
            {
                LOCKDAI_LOG_I("calibrate finished");
                Motor_SaveDirection();
                lockCalibFlag = SET;  // 开锁成功即是标记锁已完成校准
                motorError    = ERR_NO_ERROR;
                /* 上报上锁方向 */
                Lock_MotorDirReport(Motor_GetDirection());
                /* 更新上锁方向 */
                if (Motor_GetDirection() == MOTO_DIR_CCW)
                {
                    lockedDir = LOCKED_DIR_CW;
                }
                else
                    lockedDir = LOCKED_DIR_CCW;
            }
            //4.开锁到位并回拖完成
            OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);
            if(unlockSensor == LOCK_SENSOR_RESET)//此时还没有把门开锁,说明开锁失败
            {
                LOCKDAI_LOG_W("unlock failed");
                lockMsg.lock = LOCK_ACTION_INVALID;//消息上报
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            }
            else//门锁上了,说明开锁成功
            {
                LOCKDAI_LOG_I("unlock succeed");
                lockMsg.lock = LOCK_ACTION_UNLOCK;//消息上报
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            }
            motorError = ERR_NO_ERROR;
            motorStatus.current = MOTOR_STA_IDLE;//标记锁的状态为空闲
        }
    }
    //开锁传感器(下光耦)到位了，此处情况有2种: 
    //1.上次执行开锁操作,导致开锁到位了,此时需要执行开锁回拖操作 
    //2.上次执行了开锁回位操作,此时不需要执行开锁回拖操作了
    else//开锁传感器到位了,执行开锁回拖
    {
        if(repeatCount == repeatTotal + 1)//情况2,不需要执行回拖操作
        {
            LOCKDAI_LOG_W("unlock failed");
            motorError = ERR_LOCK_ERROR;
            repeatCount = 0;
            OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);

            lockMsg.lock = LOCK_ACTION_INVALID;//消息上报
            OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));

            motorError = ERR_NO_ERROR;
            motorStatus.current = MOTOR_STA_IDLE;
        }
        else//情况1,需要执行回拖操作
        {
            if(g_current_step == LOCK_STEP_FOUND_DEST)
            {
                motorError = ERR_NO_ERROR;
                unLockBack = SET;
                Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BACK, MOTOR_PARAM_BACK_TIMEOUT);
            }
            else if(g_current_step == LOCK_STEP_BACKED)
            {
                OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);
                if (unlockSensor == LOCK_SENSOR_RESET)  // 此时还没有把门开锁,说明开锁失败
                {
                    LOCKDAI_LOG_W("unlock failed");
                    lockMsg.lock = LOCK_ACTION_INVALID;  // 消息上报
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
                else  // 门锁上了,说明开锁成功
                {
                    LOCKDAI_LOG_I("unlock succeed");
                    lockMsg.lock = LOCK_ACTION_UNLOCK;  // 消息上报
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
                motorError = ERR_NO_ERROR;
                motorStatus.current = MOTOR_STA_IDLE;//标记锁的状态为空闲
            }

        }
    }
}

/**
  * @brief  传感器测试流程结束
  *         
  * @note   
  */
static void Lock_Hall_OC_Test_End(void)
{
    if(sensorTestSetp == SENSOR_TESTSETP_START)
    {
        sensorTestSetp = SENSOR_TESTSETP_END;
        Motor_SetDirection(MOTO_DIR_CCW);
        Lock_SwitchMotorStatus(MOTOR_STA_LOCKED, MOTOR_PARAM_TURN_TIMEOUT);
    }
    else if(sensorTestSetp == SENSOR_TESTSETP_END)
    {
        sensorTestSetp = SENSOR_TESTSETP_RESET;//CW
        Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK, MOTOR_PARAM_TURN_TIMEOUT);
    }
    else if(sensorTestSetp == SENSOR_TESTSETP_RESET)
    {
        LockMsg_t lockMsg;        

        memset(&lockMsg, 0, sizeof(lockMsg));
        lockMsg.sensorTestStatus[0] = (uint8_t)sensorTestRet;  
 
        if(lockMsg.sensorTestStatus[0] == ((1<<HALL_CENTER) 
#if(LOCK_DAI_HALL_NUM != 1)
        | (1<<HALL_LEFT) 
        | (1<<HALL_RIGHT) 
#endif
        | (1<<OC_UNLUCK) | (1<<OC_LUCKED)| (1<<BLADE_LEFT) | (1<<BLADE_RIGHT)))
        {
            lockMsg.sensorTestStatus[1] = 0x00;
        } 
        else 
        {
            lockMsg.sensorTestStatus[1] = 0x05;//0x05,光耦挡片异常
        }
        OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));     //消息上报

        sensorTestSetp = SENSOR_TESTSETP_INIT;
        motorStatus.current = MOTOR_STA_IDLE;
        OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);
        LOCKDAI_LOG_D("hall oc blade test result:%d,%d",sensorTestRet,lockMsg.sensorTestStatus[1]);
    }
    LOCKDAI_LOG_D("sensorTestSetp :%d", sensorTestSetp);
}

/**
  * @brief  电机运行结束处理
  *         
  * @note   
  */
static void Lock_MotorTurnEnd(void)
{
	LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
    
    if(lockedMode == LOCKED_MODE_HALL_OC_TEST)//传感器测试模式
    {
        Lock_Hall_OC_Test_End();
    }
    else
    {
        if (motorError == ERR_BACK_TIMEOUT || motorError == ERR_BACK_DCI || motorError == ERR_RESET_TIMEOUT ||
            motorError == ERR_RESET_DCI) /* 产生了锁体回拖超时、回拖过流、回位超时、回位过流错误 */
        {
            LOCKDAI_LOG_W("back/reset error");
            OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_MONITOR);
            lockMsg.lock = LOCK_ACTION_INVALID;  //消息上报
            OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            motorError          = ERR_NO_ERROR;
            motorStatus.current = MOTOR_STA_IDLE;
        }
        else if (lockStatus == LOCK_STA_LOCKING)
        {
            /* 处理上锁流程结束 */
            Lock_MotorLockedEnd();
        }
        else if (lockStatus == LOCK_STA_UNLOCKING)
        {
            /* 处理开锁流程结束 */
            Lock_MotorUnlockEnd();
        }
    }


    if(motorStatus.current ==  MOTOR_STA_IDLE)
    {
        if (lockedMode != LOCKED_MODE_KEY_TEST)
        {
            Lock_CtrlClose();
        }
    }
}

/**
  * @brief  电机运行超时
  *         
  * @note   
  */
static void Lock_MotorTimeout(void)
{
	switch (motorStatus.current)
	{
		case MOTOR_STA_LOCKED:      //上锁超时
            motorError = ERR_LOCKED_TIMEOUT; 
            break;
		case MOTOR_STA_UNLOCK:      //开锁超时  
            motorError = ERR_UNLOCK_TIMEOUT; 
            break;
		case MOTOR_STA_LOCKED_BACK: //上锁回拖超时
            motorError = ERR_BACK_TIMEOUT;   
            break;
        case MOTOR_STA_UNLOCK_BACK: //开锁回拖超时
            motorError = ERR_BACK_TIMEOUT;   
            break;
        case MOTOR_STA_LOCKED_RESET: //上锁回位超时
            motorError = ERR_RESET_TIMEOUT;   
            break;
        case MOTOR_STA_UNLOCK_RESET: //开锁回位超时
            motorError = ERR_RESET_TIMEOUT;   
            break;
		default: 
            break;
	}
    LOCKDAI_LOG_I("motorError:%d", motorError);
    if (MOTOR_STA_STOP == motorStatus.current)         
	{
        if(g_BrakeFlag)//换向标志
        {
            g_BrakeFlag = DISABLE;
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_CHANGE_DIR_TIME); 
        }
        else
        {
            /* 电机STOP 超时 *///
            Lock_MotorTurnEnd();
        }
    }
    else if (MOTOR_STA_LOCKED_BRAKE == motorStatus.current || 
            MOTOR_STA_UNLOCK_BRAKE == motorStatus.current||
            MOTOR_STA_LOCKED_BACK_BRAKE == motorStatus.current ||
            MOTOR_STA_UNLOCK_BACK_BRAKE == motorStatus.current)
	{
        /* 上锁/开锁刹车超时 */
        if(motorError == ERR_LOCKED_DCI)//上锁过流导致的刹车超时
        {
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_BLOCKED_LOCKED_TIME);
        }
        else if(motorError == ERR_UNLOCK_DCI)//开锁过流导致的刹车超时
        {
            if(lockedBlock)//上锁堵塞过程中,开锁过流导致的刹车超时,设置为1000ms
            {
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_BLOCKED_LOCKED_TIME);
            }
            else
            {
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_BLOCKED_UNLOCK_TIME);
            }
        }
        else
        {
#ifdef STOP_TO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_BRAKE_TIME);//刹车
#else
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_CHANGE_DIR_TIME);//刹车准备换向
#endif
        }
    }
    else
    {
		/* 上锁超时、开锁超时、回拖超时、*/
        Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_STOP_TIME1);
    }
}

/**
  * @brief  检查电机电流
  *         
  * @note   只有以下三种电机状态，才需要检查电流：
  *         MOTOR_STA_LOCKED：上锁状态
  *         MOTOR_STA_UNLOCK：开锁状态
  *         MOTOR_STA_BACK：回拖状态
  */
static void Lock_MotorCheckDCI(void)
{
	int16_t adcValue;
	static uint8_t overflowCnt = 0;

	switch (motorStatus.current)
	{
		case MOTOR_STA_LOCKED: 
		case MOTOR_STA_UNLOCK: 
		case MOTOR_STA_LOCKED_BACK: 
        case MOTOR_STA_UNLOCK_BACK: 
            break;
		default: 
            return;
	}

    adcValue = (int16_t)Device_Read(LOCK_DCI_ADC_CHANNEL, NULL, 0, 0);
    if (adcValue >= MOTOR_PARAM_MAX_DCI_VALUE)
    {
        overflowCnt++;
        if (overflowCnt >= MOTOR_BLOCKED_FILETERED_TIMES)
        {
            LOCKDAI_LOG_W("block vol:%d ", adcValue);
            overflowCnt = 0;
            /* 连续10次过流：标记错误情况，电机进入STOP状态 */
            if (motorStatus.current == MOTOR_STA_LOCKED)  // 上锁过流
            {
                motorError  = ERR_LOCKED_DCI;
                lockedBlock = SET;
#ifdef NO_BRAKE
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_BLOCK_STOP_TIMEOUT);
#else
                Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BRAKE, MOTOR_PARAM_BRAKE_TIME);  // 上锁过流刹车
#endif
            }
            else if (motorStatus.current == MOTOR_STA_UNLOCK)  // 开锁过流
            {
                motorError = ERR_UNLOCK_DCI;
#ifdef NO_BRAKE
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_BLOCK_STOP_TIMEOUT);
#else
                Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BRAKE, MOTOR_PARAM_BRAKE_TIME);  // 开锁过流刹车
#endif
            }
            else if (motorStatus.current == MOTOR_STA_LOCKED_BACK || motorStatus.current == MOTOR_STA_UNLOCK_BACK)  // 回拖过流
            {
                motorError = ERR_BACK_DCI;
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_BLOCK_STOP_TIMEOUT);  // 回拖过流停止
            }
            else if (motorStatus.current == MOTOR_STA_LOCKED_RESET || motorStatus.current == MOTOR_STA_UNLOCK_RESET)  // 回位过流
            {
                motorError = ERR_RESET_DCI;
#ifdef NO_BRAKE
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_BLOCK_STOP_TIMEOUT);
#else
                Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BRAKE, MOTOR_PARAM_BRAKE_TIME);  // 回位过流刹车
#endif
            }
            else
            {
                Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_BLOCK_STOP_TIMEOUT);
            }
        }
    }
    else
    {
        overflowCnt = 0;
    }
}

/**
  * @brief  电机运行状态监控（电机监控事件）
  *         
  * @note   监控电机电流、超时
  *         电机状态不等于MOTOR_STA_IDLE时：该函数每间隔10ms运行一次
  */
static void Lock_MotorMonitor(void)
{
    const uint32_t xTicks = OSAL_GetTickCount();
    uint32_t pastTime;
    pastTime = OSAL_PastTime(xTicks, motorStatus.startTime);    
	if (pastTime >= motorStatus.timeout)
	{
		Lock_MotorTimeout();    /* 处理电机当前状态超时 */
	}
	else if (pastTime >= MOTOR_PARAM_DCI_DETECT_DELAY_TIME)
	{
		Lock_MotorCheckDCI();   /* 检查电机运行电流（DCI） */
	}
}

/**
  * @brief  上锁接口函数
  *         
  * @note   
  */
static ErrorStatus Lock_Locked(void)
{
    if (lockedSensor == LOCK_SENSOR_SET && backLockedSensor == LOCK_SENSOR_SET)//上锁到位,上锁回拖到位
    {
        motorError = ERR_NO_ERROR;
        lockStatus = LOCK_STA_LOCKED;//已上锁
    }
    else
    {
        repeatCount = 0;
        lockStatus = LOCK_STA_LOCKING;
        Lock_CtrlOpen();
        OSAL_EventRepeatCreate(COMP_LOCK, EVENT_MOTOR_MONITOR, MOTOR_MONITOR_TIME, EVT_PRIORITY_HIGH);
        Lock_SwitchMotorStatus(MOTOR_STA_LOCKED, MOTOR_PARAM_TURN_TIMEOUT);
        return SUCCESS;
    }
    return ERROR;
}

/**
  * @brief  开锁接口函数
  *         
  * @note   
  */
static ErrorStatus Lock_Unlock(void)
{
    if (unlockSensor == LOCK_SENSOR_SET)
    {
        motorError = ERR_NO_ERROR;
        lockStatus = LOCK_STA_UNLOCK;//已开锁
    }
    else
    {
        repeatCount = 0;
        lockStatus = LOCK_STA_UNLOCKING;
        Lock_CtrlOpen();
        OSAL_EventRepeatCreate(COMP_LOCK, EVENT_MOTOR_MONITOR, MOTOR_MONITOR_TIME, EVT_PRIORITY_HIGH);
        Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK, MOTOR_PARAM_TURN_TIMEOUT);
        return SUCCESS;
    }
    return ERROR;
}

/**
 * @brief Lock组件API函数类型
 * 
 */
static ErrorStatus Lock_Ctrl_Sub(LockCtrl_enum_t ctrl)
{
    LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
    lockedMode = LOCKED_MODE_NORMAL;//标记为正常模式
    LOCKDAI_LOG_I("Lock_Ctrl:%d", ctrl);

    if (motorStatus.current != MOTOR_STA_IDLE)//非空闲状态下报锁体繁忙,不能执行锁体操作
    {
        lockMsg.lock = LOCK_ACTION_BUSY;
        OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
        LOCKDAI_LOG_W("lock busy");
        return ERROR;
    }

    if(lockCalibFlag == RESET)//未校准状态,开关锁前,需要调用该函数
    {
        LOCKDAI_LOG_W("not calibrate");//未校准
#ifdef LR_DISTINGUISHABLE    
        if(lockedDir == LOCKED_DIR_UNKNOWN)//上锁方向未知,以NV保存的上锁方向为准
        {
            Motor_UpdateDirection();
        }    
        else//已知上锁方向,此时需要设置电机的上锁方向  //不适用KS项目的关锁霍尔逻辑
        {
            lockCalibFlag = SET;//直接设置为已经校准状态
            if(lockedDir == LOCKED_DIR_CW)//顺时针上锁
            {
                Motor_SetDirection(MOTO_DIR_CCW);
            }
            else
            {
                Motor_SetDirection(MOTO_DIR_CW);
            }
            Motor_SaveDirection();
            /* 上报上锁方向 */
            Lock_MotorDirReport(Motor_GetDirection());
        }
#endif        
    }
    /* 变量置位 */
    g_current_step = LOCK_STEP_START;
    lockedBlock = RESET;
    lockedBlockPhase = LOCKED_BLOCK_INIT;
    lockedBack = RESET;
    unLockBack = RESET;
    switch((uint8_t)ctrl)
    {
        case LOCK_CTRL_LOCKED:
            if(lockedSensor == LOCK_SENSOR_SET && unlockSensor == LOCK_SENSOR_RESET)//门已锁上
            {
                lockMsg.lock = LOCK_ACTION_LOCKED;
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            }
            else//门未锁上
            {
                Lock_Locked();
            }
            break;
        case LOCK_CTRL_UNLOCK:
            if(unlockSensor == LOCK_SENSOR_SET && lockedSensor == LOCK_SENSOR_RESET)//门已开锁
            {
                lockMsg.lock = LOCK_ACTION_UNLOCK;
                OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            }
            else//门未开锁
            {
                Lock_Unlock();
            }
            break; 
        case LOCK_CTRL_INVERSE:
            if(lockedSensor == LOCK_SENSOR_SET)//门已锁上,则执行开锁操作
            {
                Lock_Unlock();
            }
            else//其他状态,执行上锁操作
            {
                Lock_Locked();
            }
            break; 
        default:
            break;
    }
    return SUCCESS;
}

/**
  * @brief  产测模式操作上锁/开锁的接口
  * @note   
  *         
  * @param  testMode：测试模式, LOCK_UNLOCK_TEST_MODE:上锁/开锁测试 MOTOR_TEST_MODE:电机测试
  * @param  data：控制参数
  * @param  dataLen:控制参数的个数
  */
static uint16_t Lock_TestCtrl_Sub(Lock_Test_Mode_enum_t testMode, uint8_t data[], uint8_t dataLen)
{
    if(testMode == LOCK_UNLOCK_TEST_MODE)//上锁/开锁测试
    {
        LockMsg_t lockMsg;
        uint8_t ctrl = data[0];
        //uint8_t dir = data[1];

        memset(&lockMsg, 0, sizeof(lockMsg));
        lockedMode = LOCKED_MODE_TEST;          //标记为测试模式
        lockCalibFlag = RESET;                  //保证任意位置可开关锁
        if (motorStatus.current != MOTOR_STA_IDLE)//非空闲状态下报锁体繁忙,不能执行锁体操作
        {
            lockMsg.lock = LOCK_ACTION_BUSY;
            OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
            LOCKDAI_LOG_W("lock busy");
            return ERROR;
        }

        /* 变量置位 */
        g_current_step = LOCK_STEP_START;
        lockedBlock = RESET;
        lockedBlockPhase = LOCKED_BLOCK_INIT;
        lockedBack = RESET;
        unLockBack = RESET;
        switch((uint8_t)ctrl)
        {
            case LOCK_CTRL_LOCKED:
                if(lockedSensor == LOCK_SENSOR_SET)//门已锁上
                {
                    lockMsg.lock = LOCK_ACTION_LOCKED;
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
                else//门未锁上
                {
                    Lock_Locked();
                }
                break;
            case LOCK_CTRL_UNLOCK:
                if(unlockSensor == LOCK_SENSOR_SET)//门已开锁
                {
                    lockMsg.lock = LOCK_ACTION_UNLOCK;
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
                else//门未开锁
                {
                    Lock_Unlock();
                }
                break; 
            default:
                break;
        }
        return SUCCESS;
    }
    else if(testMode == MOTOR_TEST_MODE)//电机测试
    {
        if(dataLen < 1)//电机控制至少要有一个参数
        {
            return ERROR;
        }
        uint8_t motorCtrl = data[0];   
        if(motorCtrl != 0)
        {
            Lock_CtrlOpen();
            if(motorCtrl == 1)
            {
                Motor_TurnLeft();
            }
            if(motorCtrl == 2)
            {
                Motor_TurnRight();
            }
            if(motorCtrl == 3)
            {
                Motor_Stop();
            }
            return SUCCESS;
        }
    }
    else if(testMode == HALL_OC_TEST_MODE)//霍尔、光耦测试模式
    {
        LOCKDAI_LOG_D("entry hall oc blade test");
        g_current_step = LOCK_STEP_START;
        lockedMode = LOCKED_MODE_HALL_OC_TEST;          //标记为传感器测试模式
        sensorTestSetp = SENSOR_TESTSETP_START;         //标记为传感器测试模式的开始阶段
        sensorTestRet = 0;                              //刚开始时,测试结果清0
        Lock_CtrlOpen();
        Motor_SetDirection(MOTO_DIR_CW);                //先找初始位置
        OSAL_EventRepeatCreate(COMP_LOCK, EVENT_MOTOR_MONITOR, MOTOR_MONITOR_TIME, EVT_PRIORITY_HIGH);
        Lock_SwitchMotorStatus(MOTOR_STA_LOCKED, MOTOR_PARAM_TURN_TIMEOUT);
		return SUCCESS;
    }
    else if(testMode ==  KEY_TEST_MODE)
    {
        LOCKDAI_LOG_D("entry key test");
        lockedMode = LOCKED_MODE_KEY_TEST;
    }
    else if(testMode == SET_AUTO_CAL_FLAG_MODE)
    {
        lock_CalflagSet(SET);//设置自学习标志位
    }
    else
	{
		return SUCCESS;
	}
	return SUCCESS;
}


/**
 * @brief  校准方向、自动上锁
 * @note
 *
 *
 */
static void Lock_StartUp_Calibration(void)
{
    static FlagStatus flag = SET;
    if (flag == SET)
    {
        flag = RESET;        
    if (Motor_GetDirection() == 0XFF || lock_CalflagGet() == SET)
    {
        LOCKDAI_LOG_D("start calibrate");
        /*为解决产测后不会自学习，增加产测时下发标志，下次正常模式下上电自学习方向*/
        lock_CalflagSet(RESET);

            lockCalibFlag = RESET;//让其可再次进行自学习方向
    }
    else
    {
            lockCalibFlag = SET;//同步校准标志
    }
        if(lockCalibFlag == RESET)//未校准状态，需要进行自学习
    {
            if(unlockSensor == LOCK_SENSOR_SET)
        {
            Lock_Ctrl_Sub(LOCK_CTRL_LOCKED);
        }
        else
        {
            Lock_Ctrl_Sub(LOCK_CTRL_UNLOCK);
        }
    }
}
}

/**
  * @brief  传感器状态改变
  * @note   检测到端口有动作就会调用该函数
  *         该函数会在中断里面以回调的形式调用
  *         
  * @param  name：端口名称
  * @param  status：端口状态
  * @param  times：连按次数
  */
static void Lock_SensorStatusChange(char *name, uint8_t status, uint8_t times)
{
    LockSensorAction_t sensor;
    memset(&sensor, 0, sizeof(sensor));
    /* 锁体传感器动作暂存缓存区 */
    strncpy(sensor.name, name,sizeof(sensor.name));
    sensor.action = (UserAction_enum_t)status;
    if(sensor.action > USER_ACTION_PRESS)
    {
        return;//过滤掉不需要的长按及拓展
    }
    LOCKDAI_LOG_V("I[%s,%d]",sensor.name,status);
    OSAL_RingBufferWrite(rbHandle, &sensor);
    if (isrPendFlag != 0)
    {
        return;
    }
    isrPendFlag++;
    /* 创建ISR事件 */
    OSAL_EventCreateFromISR(COMP_LOCK);
    isrPendFlag--;

}

/**
  * @brief  传感器状态值更新
  * @note   检测到端口有动作就会调用该函数
  *         该函数会在中断里面以回调的形式调用
  *         
  */
static void Lock_SensorStatusUpdate(void)
{
    LockSensorAction_t sensor;
    LockMsg_t lockMsg;
    memset(&sensor, 0, sizeof(sensor));
    memset(&lockMsg, 0, sizeof(lockMsg));
    //TODO 处理传感器状态改变
    while (OSAL_RingBufferRead(rbHandle, &sensor) == SUCCESS)
    {
        LOCKDAI_LOG_V("U[%s,%d]", sensor.name, sensor.action);
        if(strcmp(sensor.name, "IR_LOCKED") == 0)
        {
            if(lockedMode == LOCKED_MODE_HALL_OC_TEST)//传感器测试模式
            {
                sensorTestRet |= (1 << OC_LUCKED);
            }
            //更新开锁回拖到位传感器状态
            if (g_IrPowerSwitch && sensor.action == USER_ACTION_PRESS)
            {
                backUnlockSensor = LOCK_SENSOR_SET;
            }
            else if (sensor.action == USER_ACTION_RELEASE)
            {
                backUnlockSensor = LOCK_SENSOR_RESET;
            }
        }
        else if(strcmp(sensor.name, "IR_UNLOCK") == 0)
        {
            if(lockedMode == LOCKED_MODE_HALL_OC_TEST)//传感器测试模式
            {
                sensorTestRet |= (1 << OC_UNLUCK);
                if(sensorTestSetp == SENSOR_TESTSETP_END &&  unlockSensor == LOCK_SENSOR_SET)//传感器测试模式
                {
                    sensorTestRet |= (1 << BLADE_LEFT);//左侧挡片
                    LOCKDAI_LOG_D("BLADE_LEFT");
                }
                if(sensorTestSetp == SENSOR_TESTSETP_END &&  lockedSensor == LOCK_SENSOR_SET)//传感器测试模式
                {
                    sensorTestRet |= (1 << BLADE_RIGHT);//右侧挡片
                    LOCKDAI_LOG_D("BLADE_RIGHT");
                }
            }
            //更新上锁回拖到位传感器状态
            if (g_IrPowerSwitch && sensor.action == USER_ACTION_PRESS)
            {
                backLockedSensor = LOCK_SENSOR_SET;
            }
            else if (sensor.action == USER_ACTION_RELEASE)
            {
                backLockedSensor = LOCK_SENSOR_RESET;
            }
        }
#if(LOCK_DAI_HALL_NUM != 1)     
        else if(strcmp(sensor.name, "HALL_LEFT") == 0 ||
                strcmp(sensor.name, "HALL_RIGHT") == 0)
        {
            if(strcmp(sensor.name, "HALL_LEFT") == 0)//更新上锁传感器状态
            {
                if(lockedMode == LOCKED_MODE_HALL_OC_TEST)//传感器测试模式
                {
#ifdef LR_DISTINGUISHABLE                     
                    sensorTestRet |= (1 << HALL_LEFT);//
#else                   
                    //确认是左还是右，挡片测试上报5个传感器值        
                    if(sensorTestSetp == SENSOR_TESTSETP_END && sensor.action == USER_ACTION_PRESS)//靠近，区分左侧
                    {
                        sensorTestRet |= (1 << HALL_RIGHT);//旋钮右侧
                        LOCKDAI_LOG_D("HALL_RIGHT");
                    }
                    else if(sensorTestSetp == SENSOR_TESTSETP_END && sensor.action == USER_ACTION_RELEASE)//离开，避免初始状态为关
                    {
                        sensorTestRet |= (1 << HALL_LEFT);//旋钮左侧
                        LOCKDAI_LOG_D("HALL_LEFT");
                    }
#endif
                }
                if (sensor.action == USER_ACTION_PRESS)
                {
                    leftLockedSensor = LOCK_SENSOR_SET;

                }
                else if (sensor.action == USER_ACTION_RELEASE)
                {
                    leftLockedSensor = LOCK_SENSOR_RESET;
                }
            }
#ifdef LR_DISTINGUISHABLE            
            else
            {
                if(lockedMode == LOCKED_MODE_HALL_OC_TEST)//传感器测试模式
                {
                    sensorTestRet |= (1 << HALL_RIGHT);
                }
                if (sensor.action == USER_ACTION_PRESS)
                {
                    rightLockedSensor = LOCK_SENSOR_SET;

                }
                else if (sensor.action == USER_ACTION_RELEASE)
                {
                    rightLockedSensor = LOCK_SENSOR_RESET;
                }
            }
            //左右上锁传感器两个都没上锁则没上锁,否则则是已上锁          
            if(leftLockedSensor == LOCK_SENSOR_RESET && rightLockedSensor == LOCK_SENSOR_RESET)
#else           
            if(leftLockedSensor == LOCK_SENSOR_RESET)//上电时位置只有一种情况，两个霍尔共用一个IO
#endif            
            {
                lockedSensor = LOCK_SENSOR_RESET;
                if(lockCalibFlag == RESET)
                {
                    lockedDir = LOCKED_DIR_UNKNOWN;//未上锁状态下,上锁方向是不确定的
                }
            }
#ifdef LR_DISTINGUISHABLE  
            else if (leftLockedSensor != LOCK_SENSOR_UNKNOW && rightLockedSensor != LOCK_SENSOR_UNKNOW)//修复中间位置学习问题
#else
            else
#endif              
            {
                if(lockedSensor == LOCK_SENSOR_SET)
                {
                    g_lockChgFlag = RESET;
                }
                else
                {
                    g_lockChgFlag = SET;
                }
                lockedSensor = LOCK_SENSOR_SET;
#ifdef LR_DISTINGUISHABLE  
                if(lockCalibFlag == RESET)//未校准状态,若已经是上锁状态,则可认为上锁方向已经确定,此时以霍尔传感器为准
                {
                    if(leftLockedSensor == LOCK_SENSOR_SET)
                    {
                        lockedDir = LOCKED_DIR_CCW;//上锁方向为逆时针
                    }
                    else if(rightLockedSensor == LOCK_SENSOR_SET)
                    {
                        lockedDir = LOCKED_DIR_CW;//上锁方向为顺时针
                    }
                }  
#endif                                  
            }
            if(lockedSensor != LOCK_SENSOR_UNKNOW)
            {
                Lock_StartUp_Calibration();
            }
            //若电机空闲状态下发生上锁传感器状态变化时,则认为是机械操作,此时需要上报消息
            if((g_lockChgFlag == SET) && motorStatus.current == MOTOR_STA_IDLE && lockedSensor == LOCK_SENSOR_SET)//到位上报一次
            {

                lockMsg.lock = LOCK_ACTION_LOCKED_MACH ;
                //上报电机方向
                if(lockedMode !=  LOCKED_MODE_KEY_TEST)
                {
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }
            }
        }
#endif        
        else if(strcmp(sensor.name, "HALL_CENTER") == 0)
        {
            if(lockedMode == LOCKED_MODE_HALL_OC_TEST)//传感器测试模式
            {
                sensorTestRet |= (1 << HALL_CENTER);
            }
            //更新开锁传感器状态
            if (sensor.action == USER_ACTION_PRESS)
            {
                if(unlockSensor == LOCK_SENSOR_SET)
                {
                    g_unlockChgFlag = RESET;
                }
                else
                {
                    g_unlockChgFlag = SET;
                }
                unlockSensor = LOCK_SENSOR_SET;
#if(LOCK_DAI_HALL_NUM == 1)
                lockedSensor = LOCK_SENSOR_RESET;
#endif
            }
            else if (sensor.action == USER_ACTION_RELEASE)
            {
                unlockSensor = LOCK_SENSOR_RESET;
#if(LOCK_DAI_HALL_NUM == 1)
                if(lockedSensor == LOCK_SENSOR_SET)
                {
                    g_lockChgFlag = RESET;
                }
                else
                {
                    g_lockChgFlag = SET;
                }
                lockedSensor = LOCK_SENSOR_SET;
#endif
            }
            Lock_StartUp_Calibration();
#if(LOCK_DAI_HALL_NUM == 1)
		    if(motorStatus.current == MOTOR_STA_IDLE && ((g_lockChgFlag == SET && lockedSensor == LOCK_SENSOR_SET) || (g_unlockChgFlag == SET && unlockSensor == LOCK_SENSOR_SET)))//若电机空闲状态下发生开锁传感器状态变化时,则认为是机械操作
#else                
            if(motorStatus.current == MOTOR_STA_IDLE && g_unlockChgFlag == SET && unlockSensor == LOCK_SENSOR_SET )//若电机空闲状态下发生开锁传感器状态变化时,则认为是机械操作
#endif                
            {
#if(LOCK_DAI_HALL_NUM == 1)
                    lockMsg.lock = (unlockSensor == LOCK_SENSOR_SET) ? LOCK_ACTION_UNLOCK_MACH : LOCK_ACTION_LOCKED_MACH; 
#else
                    lockMsg.lock = LOCK_ACTION_UNLOCK_MACH;  //消息上报
#endif
                if(lockedMode !=  LOCKED_MODE_KEY_TEST)
                {
                    OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
                }     
            }
        }
        if(lockedMode ==  LOCKED_MODE_KEY_TEST)
        {
            OSAL_MessagePublish(&sensor, sizeof(sensor));
        }
        if (lockedMode != LOCKED_MODE_HALL_OC_TEST && lockStatus == LOCK_STA_LOCKING && motorStatus.current == MOTOR_STA_LOCKED)  //关锁到位
        {
            if (lockedSensor == LOCK_SENSOR_SET && backUnlockSensor == LOCK_SENSOR_SET)
            {
                g_current_step = LOCK_STEP_FOUND_DEST; 
            }
        }
        else if (lockedMode != LOCKED_MODE_HALL_OC_TEST && lockStatus == LOCK_STA_LOCKING && motorStatus.current == MOTOR_STA_UNLOCK)  //关时堵转切换开的方向
        {
            if (lockCalibFlag == RESET && unlockSensor == LOCK_SENSOR_SET && backUnlockSensor == LOCK_SENSOR_SET)//学习时堵转后切换方向到回拖位置再试
            {
                g_current_step = LOCK_STEP_BACKED;
            }
            else if (lockCalibFlag == SET && unlockSensor == LOCK_SENSOR_SET && backLockedSensor == LOCK_SENSOR_SET)//堵转锁舌缩回到位再试
            {
                g_current_step = LOCK_STEP_BACKED; 
            }
        }
        else if (lockedMode != LOCKED_MODE_HALL_OC_TEST && lockStatus == LOCK_STA_UNLOCKING && motorStatus.current == MOTOR_STA_UNLOCK) //开锁到位**
        {
            if (unlockSensor == LOCK_SENSOR_SET && backLockedSensor == LOCK_SENSOR_SET)
            {
                g_current_step = LOCK_STEP_FOUND_DEST;
            }
        }
        else if ((motorStatus.current == MOTOR_STA_LOCKED_BACK && backLockedSensor == LOCK_SENSOR_SET) || (motorStatus.current == MOTOR_STA_UNLOCK_BACK && backUnlockSensor == LOCK_SENSOR_SET))  // 回拖到位停止
        {
            g_current_step = LOCK_STEP_BACKED;
        }     
        else if (motorStatus.current == MOTOR_STA_LOCKED_RESET)
        {
            if (backUnlockSensor == LOCK_SENSOR_SET || (lockCalibFlag == SET && backLockedSensor == LOCK_SENSOR_SET))  // 上锁回位到位不刹车 backLockedSensor修复未堵死锁舌伸出一部分回位导致反向旋钮带电机的情况
            {
                g_current_step = LOCK_STEP_RESET;
            }
        }
        else if (motorStatus.current == MOTOR_STA_UNLOCK_RESET)
        {
            if (backLockedSensor == LOCK_SENSOR_SET || (lockCalibFlag == SET && backUnlockSensor == LOCK_SENSOR_SET) )  // 开锁回位到位不刹车 backUnlockSensor修复未堵死锁舌回缩一部分回位导致旋钮反向带电机的情况
            {
                g_current_step = LOCK_STEP_RESET;
            }
        }
        LOCKDAI_LOG_V("dir:%d sensor status:%d, %d, %d, %d",lockedDir,lockedSensor,backLockedSensor,unlockSensor,backUnlockSensor);
    }
}

/**
  * @brief  锁体启动
  *         
  * @note   
  */
static void Lock_Start(void)
{
    if (rbHandle == NULL)
    {
        /* 电机PWM配置 */
        Motor_PwmInit();
        /* 创建环形缓存（暂存传感器状态） */
        rbHandle = OSAL_RingBufferCreate(SENSOR_MAX_RING_LEN, sizeof(LockSensorAction_t));
            
        // 掉电2S后地磁需要知道开关锁方向重新初始化，否则会一直没初始化
        OSAL_EventSingleCreate(COMP_LOCK, EVENT_LOCK_DIR_UPDATE, 2000, EVT_PRIORITY_MEDIUM);
    }


    /* 注册锁体传感器端口 */
    InputPort_stu_t sensor_list[] = {
            {"IR_LOCKED",   vPIN_B20, OCEP1_SET_LEVEL, INPUT_PORT_FUNC_SINGLE}, //红外感应：上锁到位感应
            {"IR_UNLOCK",   vPIN_B21, OCEP2_SET_LEVEL, INPUT_PORT_FUNC_SINGLE}, //红外感应：开锁到位感应
#if(LOCK_DAI_HALL_NUM != 1)
            {"HALL_LEFT",   vPIN_B22, HALL1_SET_LEVEL, INPUT_PORT_FUNC_SINGLE}, //霍尔感应：上锁到位（旋钮位置：左）
#endif
#ifdef LR_DISTINGUISHABLE
            {"HALL_RIGHT", vPIN_B23, HALL3_SET_LEVEL, INPUT_PORT_FUNC_SINGLE}, //霍尔感应：开锁到位（旋钮位置：中间） 
#endif
            {"HALL_CENTER", vPIN_B24, HALL2_SET_LEVEL, INPUT_PORT_FUNC_SINGLE}, //霍尔感应：开锁到位（旋钮位置：中间）
    };
    InputPort_Registered(sensor_list, OSAL_LENGTH(sensor_list), Lock_SensorStatusChange);

    InputPort_EnableProt("IR_LOCKED");
    InputPort_EnableProt("IR_UNLOCK");
#if(LOCK_DAI_HALL_NUM != 1)
    InputPort_EnableProt("HALL_LEFT");
#endif
#ifdef LR_DISTINGUISHABLE  
    InputPort_EnableProt("HALL_RIGHT");
#endif
    InputPort_EnableProt("HALL_CENTER");
}
/**
 * @brief  自动上锁定时器回调
 * @param  timer: 
 */
static void Auto_Lock_TimerCb(TimerHandle_stu_t timer)
{
    OSAL_EventSingleCreate(COMP_LOCK, EVENT_AUTO_LOCK, AUTO_LOCK_EVENT_TIME, EVT_PRIORITY_HIGH);
    if (Auto_Lock_Timer != NULL)
    {
        OSAL_TimerDelete(Auto_Lock_Timer);
        Auto_Lock_Timer = NULL;
    }
}

static void Lock_Dai_ProcessMbox(uint8_t *msg)
{
    switch (msg[0])
    {
		case LOCK_MBOX_CTRL:
		{
			uint8_t ctrl;
			ctrl = msg[1];
			Lock_Ctrl_Sub((LockCtrl_enum_t)ctrl);
		}
			break;
		case LOCK_MBOX_TESTCTRL:
		{
			uint8_t testMode, dataLen, data[10];
			testMode = msg[1];
			dataLen = msg[2];
			memcpy(data, &msg[3], dataLen);
			Lock_TestCtrl_Sub((Lock_Test_Mode_enum_t)testMode, data, dataLen);
		}
			break;
        case LOCK_MBOX_IR_CTRL:
        {  
            uint8_t ir_power_level;
            ir_power_level = msg[1];
            Lock_OptocoupleCtrl(ir_power_level);                      
        }
            break;
        case LOCK_MBOX_BATTERY:
        {
            uint16_t bat_vol;
            memcpy(&bat_vol, &msg[1], sizeof(bat_vol));
            LOCKDAI_LOG_D("vol = %d", bat_vol);
            if (bat_vol >= MOTOR_POWER_CTRL_VAL)
            {
                LOCK_MOTOR_POWER_HIGH_VOLTAGE();
            }
            else
            {
                LOCK_MOTOR_POWER_LOW_VOLTAGE();
            }
        }
            break;
        case LOCK_MBOX_AUTO_LOCK:
        {
            uint8_t auto_lock_cmd = msg[1];
            uint32_t aoto_lock_time;
            memcpy(&aoto_lock_time, &msg[2], sizeof(aoto_lock_time));
            LOCKDAI_LOG_D("Auto lock %d,%d", auto_lock_cmd, aoto_lock_time);
            if (auto_lock_cmd == ENABLE_AUTO_LOCK)
            {
                if (Auto_Lock_Timer != NULL)
                {
                    OSAL_TimerDelete(Auto_Lock_Timer);
                    Auto_Lock_Timer = NULL;
                }
                Auto_Lock_Timer = OSAL_TimerCreate(Auto_Lock_TimerCb, aoto_lock_time, RESET); // 创建定时器

                if (Auto_Lock_Timer == NULL)
                {
                    LOCKDAI_LOG_W("Creat auto lock timer faild");
                }
            }
            else
            {
                if (Auto_Lock_Timer != NULL)
                {
                    OSAL_TimerDelete(Auto_Lock_Timer);
                    Auto_Lock_Timer = NULL;
                }
            }
        }
            break;
        case LOCK_MBOX_SET_LOCK_DAI_DIR:
        {
            if (SUCCESS == OSAL_NvWrite(OSAL_OFFSET(LockNvData_stu_t, motor_direction), &msg[1], sizeof(lock_data.motor_direction)))
            {
                LOCKDAI_LOG_I("Lock Dir Set success %d", msg[1]);
            }
            else
            {
                LOCKDAI_LOG_W("Lock Dir Set error");
            }
        }
            break;
        default:
   
			break;
    }
}

/**
  * @brief  锁体休眠
  *         
  * @note   
  */
static void Lock_Sleep(void)
{
    LOCKDAI_LOG_I("Lock_Sleep");
    InputPort_DisableProt("IR_LOCKED");
    InputPort_DisableProt("IR_UNLOCK");
    // /* 关闭PWM和ADC */
    Device_Disable(MOTO_A_VIRTUAL_PWM);
    Device_Disable(MOTO_B_VIRTUAL_PWM);
    Device_Disable(LOCK_DCI_ADC_CHANNEL);
    /* 光耦电机断电 */
    LOCK_IR_DISABLE();
    LOCK_MOTOR_DISABLE();
    LOCK_MOTOR_POWER_SLEEP_VOLTAGE(); // 有功耗 休眠配置IO
    /* 休眠霍尔io配置 */
#if(LOCK_DAI_HALL_NUM != 1)    
    Device_Disable(SENSOR_HALL_LEFT);
#endif
#ifdef LR_DISTINGUISHABLE  
    Device_Disable(SENSOR_HALL_RIGHT);
#endif    
    Device_Disable(SENSOR_HALL_CENTER);
}



/**
 * @brief 切换方向
 * 
 */
static void Lock_SwitchDir(void)
{    
    //TODO:简化判断逻辑
    if (g_current_step == LOCK_STEP_FOUND_DEST)
    {

        if (motorStatus.current == MOTOR_STA_LOCKED)
        {
#ifdef STOP_TO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BRAKE, MOTOR_PARAM_STOP_TO_BRAKE_TIME);
#else
#ifdef NO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
#else
            Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BRAKE, MOTOR_PARAM_BRAKE_TIME);
#endif

#endif
        }
        else if (motorStatus.current == MOTOR_STA_UNLOCK)
        {
#ifdef STOP_TO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BRAKE, MOTOR_PARAM_STOP_TO_BRAKE_TIME);
#else
#ifdef NO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
#else
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BRAKE, MOTOR_PARAM_BRAKE_TIME);
#endif

#endif
        }     
    }
    else if (g_current_step == LOCK_STEP_BACKED)  // 上锁回拖到位停止
    {
        if(motorStatus.current == MOTOR_STA_LOCKED_BACK)
        {
#ifdef STOP_TO_BRAKE
        Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BACK_BRAKE, MOTOR_PARAM_STOP_TO_BRAKE_TIME);
#else
#ifdef BACK_NO_BRAKE
        Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
#else
        Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_BACK_BRAKE, MOTOR_PARAM_BRAKE_TIME);
#endif

#endif          
        }
        else if(motorStatus.current == MOTOR_STA_UNLOCK_BACK)
        {
#ifdef STOP_TO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BACK_BRAKE, MOTOR_PARAM_STOP_TO_BRAKE_TIME);
#else
#ifdef BACK_NO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
#else
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_BACK_BRAKE, MOTOR_PARAM_BRAKE_TIME);
#endif

#endif
        }
        else if(motorStatus.current == MOTOR_STA_UNLOCK)
        {
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
            g_current_step = LOCK_STEP_START;
        }
    }
    else if(g_current_step == LOCK_STEP_RESET)//上锁回位过程中检测到右光耦从未遮挡到遮挡状态则进行刹车
    {
        if (motorStatus.current == MOTOR_STA_LOCKED_RESET)
        {
#ifdef STOP_TO_BRAKE               
            Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_RESET_BRAKE, MOTOR_PARAM_STOP_TO_BRAKE_TIME);
#else
#ifdef NO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
#else
            Lock_SwitchMotorStatus(MOTOR_STA_LOCKED_RESET_BRAKE, MOTOR_PARAM_BRAKE_TIME);
#endif       
#endif          
        }
        else if(motorStatus.current == MOTOR_STA_UNLOCK_RESET)
        {
#ifdef STOP_TO_BRAKE               
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_RESET_BRAKE, MOTOR_PARAM_STOP_TO_BRAKE_TIME);
#else
#ifdef NO_BRAKE
            Lock_SwitchMotorStatus(MOTOR_STA_STOP, MOTOR_PARAM_NO_BRAKE_CHANGE_DIR_TIME);
#else
            Lock_SwitchMotorStatus(MOTOR_STA_UNLOCK_RESET_BRAKE, MOTOR_PARAM_BRAKE_TIME);
#endif
#endif                              
        }
    }
}

/**
 * @brief  锁体任务函数
 *
 * @note
 *
 * @param  event：当前任务的所有事件
 *
 * @return 返回未处理的事件
 */
static uint32_t Lock_Task(uint32_t event)
{
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		LOCKDAI_LOG_I("Lock task start");
        Motor_UpdateDirection();
#ifndef SLAVE_DEVICE        
        SYS_API(Motor_LockMotorDirSet);
        SYS_API(Lock_get_lock_status);
#endif
        Lock_Start();
		return ( event ^ EVENT_SYS_START );
	}
	if (event & EVENT_SYS_MBOX)
    {
        uint8_t buffer[30] = {0};
        while (OSAL_MboxAccept(buffer))
        {
            Lock_Dai_ProcessMbox(buffer);
        }
        return ( event ^ EVENT_SYS_MBOX );
    }
	/* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
        Lock_Sleep();
		return ( event ^ EVENT_SYS_SLEEP );
	}
 
	/* 系统中断事件 */
	if (event & EVENT_SYS_ISR)
	{
        Lock_SensorStatusUpdate();
		return ( event ^ EVENT_SYS_ISR );
	}

    /* 电机监控事件 */
    if (event & EVENT_MOTOR_MONITOR)
	{
        Lock_SwitchDir();
        Lock_MotorMonitor();
        if (motorStatus.current != MOTOR_STA_IDLE)//非空闲状态下不允许休眠
        {
            OSAL_SetTaskStatus(TASK_STA_ACTIVE);
        }
        else
        {
            OSAL_SetTaskStatus(TASK_STA_NORMAL);
        }
        return ( event ^ EVENT_MOTOR_MONITOR );
    }
    /* 自动上锁事件 */
    if (event & EVENT_AUTO_LOCK)
    {
        LockMsg_t lockMsg;
        memset(&lockMsg, 0, sizeof(lockMsg));
        lockMsg.cmd = AUTO_LOCK_START;
        OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
        return (event ^ EVENT_AUTO_LOCK);
    }

    if (event & EVENT_LOCK_DIR_UPDATE)
    {
        // 国芯前板启动慢，上电2S后才PUBLISH上锁方向
        LockMsg_t lockMsg;
        memset(&lockMsg, 0, sizeof(lockMsg));
        lockMsg.cmd = MSENSOR_REPORT_DIR;
        if (Motor_GetDirection())
        {
            lockMsg.lock = LOCK_ACTION_DIR_RIGHT;
        }
        else
        {
            lockMsg.lock = LOCK_ACTION_DIR_LEFT;
        }
        OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
        return (event ^ EVENT_LOCK_DIR_UPDATE);
    }

    return 0;
}
COMPONENT_TASK_EXPORT(COMP_LOCK, Lock_Task, sizeof(LockNvData_stu_t));
